define(
   [
      'dojo/_base/declare',
      'dojo/on',
      'dojo/dom',
      'dojo/_base/lang',
      'dojo/dom-construct',
      'graphtest/FunctionManager',
      'graphtest/DiceDistributionGenerator'
   ],
   function(declare, on, dom, lang, domConstruct, FunctionManager, DiceDistributionGenerator)
   {
      return declare([],
      	 {
      	    classCode: 'InitD3DataGraph',
      	    
      	    constructor:function(data)
      	    {
      	       console.log(this.classCode, "I'm in constructor", this.classCode);
      	       this.data = data;
      	    },
      	    
      	    postscript:function()
      	    {
      	      console.log(this.classCode, "I'm in postscript", this.classCode);
      	      
      	      on(ui.submitDice, 'click', lang.hitch(this, function()
      	        {
      	          var inputValues = this._getInputs();
      	          console.log("Inserted:",inputValues);
      	          if(inputValues)
      	          {
      	            var dg = this._getNewDiceGen(inputValues);
      	            this.data = dg.getData();
      	            this._updateGraph();
      	          }
      	        }));
      	      
      	      var margin = {top: 20, right: 20, bottom: 30, left: 40};
      	      this.width = 960 - margin.left - margin.right;
      	      this.height = 500 - margin.top - margin.bottom;
      	      
      	      var formatPercent = d3.format(".0%");
      	      
      	      this.x = d3.scale.ordinal()
      	      .rangeRoundBands([0, this.width], 0.1);
      	      
      	      this.y = d3.scale.linear()
      	      .range([this.height, 0]);
      	      
      	      var xAxis = d3.svg.axis()
      	      .scale(this.x)
      	      .orient("bottom");
      	      
      	      var yAxis = d3.svg.axis()
      	      .scale(this.y)
      	      .orient("left")
      	      .tickFormat(formatPercent);
      	      
      	      this.xAxis = xAxis;
      	      this.yAxis = yAxis;
      	      
      	      this.svg = d3.select("#graph_container").append("svg")
      	      .attr("id","svg_data_chart")
      	      .attr("width", this.width + margin.left + margin.right)
      	      .attr("height", this.height + margin.top + margin.bottom)
      	      .append("g")
      	      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      	      .on("mousemove",function()
      	            {
      	              var _this = d3.select("#selected_bar_info");
      	              var e = d3.event;
      	              _this.attr("transform", function(d)
      	                { 
      	                  return "translate(" + e.x + "," + e.y + ")";
      	                });
      	            });
      	      
      	      this.xAxisElem = this.svg.append("g");
      	      this.yAxisElem = this.svg.append("g");
      	      this.bar = this.svg.selectAll(".bar");
      	      
      	      this._updateGraph();
      	    },
      	    
      	    _updateGraph:function()
      	    {
      	      var data = this.data;
      	      
      	      var xDomain = this._getXDomain(data);
      	      var yDomain = this._getYDomain(data);
      	      var colorScaleProp = this._getColorScaleProp(yDomain);
      	      
      	      this.color = d3.scale.linear()
      	      .domain(colorScaleProp.domain)
      	      .range(colorScaleProp.range);
      	      
      	      this.x.domain(xDomain);
      	      this.y.domain(yDomain);
      	      
      	      this.xAxisElem
      	      .attr("class", "x axis")
      	      .attr("transform", "translate(0," + this.height + ")")
      	      .call(this.xAxis);
      	      
      	      this.yAxisElem
      	      .attr("class", "y axis")
      	      .call(this.yAxis)
      	      .append("text")
      	      .attr("transform", "rotate(-90)")
      	      .attr("y", 6)
      	      .attr("dy", ".71em")
      	      .style("text-anchor", "end")
      	      .text("Distribution");
      	      
      	      this.bar.remove();
      	      this.bar = this.svg.selectAll(".bar");
      	      this.bar = this.bar.data(data)
      	      .enter()
      	      .append("rect")
      	      .attr("class", "bar")
      	      .attr("x", lang.hitch(this, function(d) { return this.x(d.sum); }))
      	      .attr("width", this.x.rangeBand())
      	      .attr("y", lang.hitch(this, function(d) { return this.y(d.distribution); }))
      	      .attr("fill", lang.hitch(this, function(d)
      	        {
      	          return this.color(d.distribution);
      	        }))
      	      .attr("height", lang.hitch(this, function(d) { return this.height - this.y(d.distribution); }))
      	      .on("mouseover", function(d,i)
      	        {
      	          var _this = d3.select(this)
      	          .attr("class", "selected_bar");
      	          var e = d3.event;
      	          var r = 30;
      	          
      	          var cx = _this.attr("width")/2;
      	          cx += parseFloat(_this.attr("x"));
      	          //var cx = e.x;
      	          
      	          var cy = -r;
      	          cy += parseFloat(_this.attr("y"));
      	          //var cy = e.y;
      	          
      	          console.log("cx",cx);
      	          console.log("cy",cy);
      	          
      	          d3.select(this.parentNode)
      	          .append("circle")
      	          .attr("r",r)
      	          .attr("id","selected_bar_info")
      	          .attr("class","info_circle");
      	          
      	        })
      	      .on("mouseout", function()
      	        {
      	          d3.select(this).attr("class", "bar");
      	          d3.select("#selected_bar_info").remove();
      	        });
      	    },
      	    
      	    _getXDomain:function(data)
      	    {
      	      var domain = [];
      	      data.forEach(function(d)
      	        {
      	          domain.push(d.sum);
      	        });
      	      return domain;
      	    },
      	    
      	    _getYDomain:function(data)
      	    {
      	      var maxValue = -1.0;
      	      data.forEach(function(v)
      	        {
      	          var val = v.distribution;
      	          maxValue = maxValue < val ? val : maxValue; 
      	        });
      	      return [0, maxValue+0.01];
      	    },
      	    
      	    _getColorScaleProp:function(yDomain)
      	    {
      	      var prop =
      	      {
      	        domain: [yDomain[0], yDomain[1]*(2/3),yDomain[1]],
      	        range: ["blue", "yellow", "red"]
      	      };
      	      
      	      return prop;
      	    },
      	    
      	    type:function(d) {
      	      d.distribution = +d.distribution;
      	      return d;
      	    },
      	    
      	    _getInputs:function()
      	    {
      	      var res =
      	      {
      	        faceNumber: ui.faceNumber.get("value"),
      	        dicesNumber: ui.diceNumber.get("value")
      	      };
      	      
      	      return ui.faceNumber.validate() && ui.diceNumber.validate() ?
      	             res : undefined;
      	    },
      	    
      	    _getNewDiceGen:function(inputValues)
      	    {
      	      var faces = [];
      	      for(var f=1; f<=inputValues.faceNumber; f++)
      	      {
      	        faces.push(f);
      	      }
      	      
      	      mo.diceDistributionGenerator = new DiceDistributionGenerator();
      	      
      	      var opt =
      	      {
      	        faces: faces,
      	        dicesNumber: inputValues.dicesNumber
      	      };
      	      
      	      mo.diceDistributionGenerator.setup(opt);
      	      mo.diceDistributionGenerator.startCalculateDistribution();
      	      mo.diceDistributionGenerator.printRes();
      	      console.log(mo.diceDistributionGenerator.getData());
      	      return mo.diceDistributionGenerator;
      	    },
      	    
      	    endOfLib:null
      	 });
   });